package QL;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.util.StringUtils;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class QLClient {
    public final static String APP_KEY = "app_key";  //应用key的 字段名(不动)
    public final static String SIGN = "sign";  //签名字段名
    public final static String SIGN_METHOD = "sign_method";  //签名方法字段名
    public final static String FORMAT = "format";  //接受的响应格式字段名(json xml)
    public final static String METHOD = "method"; //请求方法字段名
    public final static String TIMESTAMP = "timestamp";
    public final static String SDK_VERSION = "sdk_version";
    public final static String SESSION = "session";
    public final static String SDK_VERSION_VALUE = "ql-sdk-20160128";

    public final static String Key = "SuperAdministrator";  //应用key
    public final static String Password = "E8oN05kGjH3aHmBL";  //密钥
    public static String ServerUrl = "http://118.24.113.66:8000/router/rest";  //域名
    public final static String ResponseFormat = "Json";

    public static void Execute(IQLRequest req, BaseQLResponse rsp) {
        // 检查业务参数
        try {
            req.Validate();
        } catch (QLException e) {
            rsp.ErrCode = String.valueOf(e.getErrorCode());
            rsp.ErrMsg = e.getMessage();
            return;
        }

        // 准备字段
        HashMap<String, String> map = new HashMap<String, String>();
        req.AddParameters(map);

        //移除空元素
        for (Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); it.hasNext();){
            Entry<String, String> item = it.next();
            if (StringUtils.isEmpty(item.getValue()))
            {
                it.remove();
            }
        }

        map.put(METHOD, req.GetApiName());
        map.put(SIGN_METHOD, "md5");
        map.put(APP_KEY, Key);
        map.put(FORMAT, ResponseFormat);
        map.put(SDK_VERSION, SDK_VERSION_VALUE);
        map.put(TIMESTAMP, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));

        // 计算签名
        map.put(SIGN, calculateSignResult(map, Password));
        // 拼接内容
        String parameterString = contactParameters(map);
//        System.out.println(parameterString);
        // 准备发送
        String content = doPost(ServerUrl, parameterString);
        // 反序列化
        JSONObject data = JSONObject.fromObject(content);
        rsp.DeserializeFromJson(data);
    }

    private static String calculateSignResult(HashMap<String, String> map, String Password) {
        List<String> keys = new ArrayList<String>();
        keys.addAll(map.keySet());

        Collections.sort(keys, new Comparator<String>() {
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });

        StringBuilder sb = new StringBuilder();
        sb.append(Password);
        for (String s : keys)
        {
            sb.append(s);
            sb.append(map.get(s));
        }
        sb.append(Password);
        return MD5.MD5Encode(sb.toString(), "UTF-8");
    }

    private static String contactParameters(Map<String, String> map) {
        StringBuilder sb = new StringBuilder();

        try {
            boolean hasParam = false;
            for (Map.Entry<String, String> pair : map.entrySet()) {
                if (!hasParam) {
                    hasParam = true;
                }
                else {
                    sb.append('&');
                }
                sb.append(pair.getKey());
                sb.append('=');
                sb.append(URLEncoder.encode(pair.getValue(), "utf-8"));
            }
        } catch (Exception e) {

        }
        return sb.toString();
    }

    private static String doPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！"+e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
    }
}
